package org.dt.common.enums;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 保存枚举值和枚举对象的映射关系。 利用枚举值（外部传入或者数据库读取出来的）反向查找出枚举对象。
 * <p>
 * 使用之前会初始化映射关系。
 * <p>
 * 该类为线程安全的。
 *
 * @author wangfeng
 */
public class ResolvableEnumRegistry {

    private static ConcurrentHashMap<Class<?>, HashMap<Object, Enum<?>>> registries = new ConcurrentHashMap<>();

    /**
     * 根据枚举对象的索引值查找出枚举对象
     *
     * @param clazz     枚举类的class类型
     * @param enumValue 枚举对象的索引值
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <E extends Enum<E>> E findEnum(Class<E> clazz, Object enumValue) {
        HashMap<Object, Enum<?>> registry = registries.get(clazz);
        if (registry == null) {
            registry = new HashMap<>();
            initRegistry(clazz, registry);

            registries.put(clazz, registry);
        }

        return (E) registry.get(enumValue);
    }

    private static <E extends Enum<E>> void initRegistry(Class<E> clazz, HashMap<Object, Enum<?>> registry) {
        if (ResolvableEnum.class.isAssignableFrom(clazz)) {
            for (E e : EnumSet.allOf(clazz)) {
                ResolvableEnum findableEnum = (ResolvableEnum) e;
                registry.put(findableEnum.getEnumKey(), e);
            }
        } else {
            throw new IllegalStateException("class " + clazz.getSimpleName() + " is not inherited from "
                                            + ResolvableEnum.class.getSimpleName());
        }
    }

}
